package com.dc.kylin.logbackdesensitization.utils;

import com.dc.kylin.logbackdesensitization.config.DesensitizationProperties;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class DesensitizationUtils {

    private static DesensitizationProperties properties;
    private static List<PatternRule> patternRules = new ArrayList<>();
    private static ExecutorService executorService;
    private static int maxLogLength;

    public static void init(DesensitizationProperties props) {
        properties = props;
        maxLogLength = props.getConcurrent().getMaxLogLength();

        // 初始化线程池用于高并发处理
        executorService = new ThreadPoolExecutor(
                4,
                8,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );


        // 编译正则表达式规则
        for (DesensitizationProperties.DesensitizationRule rule : props.getRules()) {
            Pattern pattern = Pattern.compile(rule.getPattern());
            patternRules.add(new PatternRule(pattern, rule.getReplacement(), rule.getCustom()));
        }

        log.info("脱敏工具初始化完成，加载规则数量: {}", patternRules.size());
    }

    public static String desensitize(String content) {
        log.info("开始执行desensitize方法，获取到的: {}", content);
        if (content == null || content.isEmpty()) {
            return content;
        }

        // 高并发处理：如果日志过长，先截取处理
        if (content.length() > maxLogLength) {
            return processLongContent(content);
        }

        return processContent(content);
    }

    private static String processLongContent(String content) {
        try {
            // 使用CompletableFuture进行并行处理
            int partSize = content.length() / 4;
            List<CompletableFuture<String>> futures = new ArrayList<>();

            for (int i = 0; i < 4; i++) {
                int start = i * partSize;
                int end = (i == 3) ? content.length() : (i + 1) * partSize;
                String part = content.substring(start, end);

                CompletableFuture<String> future = CompletableFuture.supplyAsync(
                        () -> processContent(part),
                        executorService
                );
                futures.add(future);
            }

            // 合并结果
            CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                    futures.toArray(new CompletableFuture[0])
            );

            CompletableFuture<String> combinedFuture = allFutures.thenApply(v -> {
                StringBuilder result = new StringBuilder();
                futures.forEach(f -> result.append(f.join()));
                return result.toString();
            });

            return combinedFuture.get(properties.getConcurrent().getTimeoutMs(), TimeUnit.MILLISECONDS);

        } catch (Exception e) {
            log.warn("并行脱敏处理失败，回退到串行处理", e);
            // 超时或其他异常时，直接截取前maxLogLength字符进行处理
            String truncated = content.substring(0, maxLogLength);
            return processContent(truncated) + "...[TRUNCATED]";
        }
    }

    private static String processContent(String content) {
        String result = content;
        for (PatternRule rule : patternRules) {
            if (rule.isCustom()) {
                result = applyCustomRule(result, rule);
            } else {
                result = applyStandardRule(result, rule);
            }
        }
        return result;
    }

    private static String applyStandardRule(String content, PatternRule rule) {
        StringBuffer sb = new StringBuffer();
        Matcher matcher = rule.getPattern().matcher(content);
        while (matcher.find()) {
            matcher.appendReplacement(sb, rule.getReplacement());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    private static String applyCustomRule(String content, PatternRule rule) {
        // 处理自定义规则，如姓名的动态长度替换
        if (rule.getReplacement().contains("repeat")) {
            return processNameDesensitization(content, rule);
        }
        return applyStandardRule(content, rule);
    }

    private static String processNameDesensitization(String content, PatternRule rule) {
        Pattern pattern = rule.getPattern();
        Matcher matcher = pattern.matcher(content);
        StringBuffer sb = new StringBuffer();

        while (matcher.find()) {
            String fullMatch = matcher.group(0);
            String firstChar = matcher.group(1);
            String remaining = matcher.group(2);

            // 根据剩余长度生成对应数量的*
            String stars = "*".repeat(remaining.length());
            String replacement = firstChar + stars;

            matcher.appendReplacement(sb, replacement);
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static void shutdown() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }

    private static class PatternRule {
        private final Pattern pattern;
        private final String replacement;
        private final boolean custom;

        public PatternRule(Pattern pattern, String replacement, boolean custom) {
            this.pattern = pattern;
            this.replacement = replacement;
            this.custom = custom;
        }

        public Pattern getPattern() { return pattern; }
        public String getReplacement() { return replacement; }
        public boolean isCustom() { return custom; }
    }
}
